import { IS_PROD } from "@/config/constant"

/**
 * 定义日志等级枚举
 */
const enum LogLevel {
    Info,
    Warning,
    Error,
}

/**
 * 不同的日志等级对应不同的颜色
 */
const Styles = ['color: green;', 'color: orange;', 'color: red;']

/**
 * 日志方法
 */
const Methods = ['info', 'warn', 'error'] as const

/**
 * 日志的配置类型
 */
type LoggerConfigType = {
    /** 命名空间 */
    namespace?: string
}

/**
* 拦截器函数类型
*/
type InterceptorFuncType = (config: LoggerConfigType) => void

class Logger {
    private beforeFuncs: Array<InterceptorFuncType> = []
    private afterFuncs: Array<InterceptorFuncType> = []
    private config: LoggerConfigType = {}

    constructor(namespace = 'unknown') {
        this.config.namespace = namespace
    }

    public create(namespace = 'unknown') {
        return new Logger(namespace)
    }

    private _log(level: LogLevel, args: unknown[]) {
        if (IS_PROD) return
        console[Methods[level]](`%c${this.config.namespace}`, Styles[level], ...args)
    }

    /**
     * 打印输出信息
     *
     * @param args 任意参数
     */
    public info(...args: unknown[]) {
        this._log(LogLevel.Info, args)
        return this
    }

    /**
     * 打印输出警告信息
     *
     * @param args 任意参数
     */
    public warn(...args: unknown[]) {
        this._log(LogLevel.Warning, args)
        return this
    }

    /**
     * 打印输出错误信息
     *
     * @param args 任意参数
     */
    public error(...args: unknown[]) {
        this._log(LogLevel.Error, args)
        return this
    }

    /**
     * 设置命名空间（日志前缀）
     * @param namespace
     */
    public setNamespace(namespace = '') {
        this.config.namespace = `[${namespace}]`
        return this
    }

    /**
     * 增加拦截器（方便扩展）
     * @param func 
     * @param isBefore 
     * @returns 
     */
    private addInterceptor(func: InterceptorFuncType, isBefore = true) {
        if (typeof func != 'function') {
            return this.error("拦截器类型异常")
        }
        if (isBefore) {
            this.beforeFuncs.push(func)
            return this;
        }
        this.afterFuncs.push(func)
        return this
    }

    /**
     * 调用打印日志之前
     * @param func 
     * @returns 
     */
    public addBeforeFunc(func: InterceptorFuncType) {
        return this.addInterceptor(func)
    }

    /**
     * 调用打印日志之后
     * @param func 
     * @returns 
     */
    public addAfterFunc(func: InterceptorFuncType) {
        return this.addInterceptor(func, false)
    }
}

export default new Logger()